﻿/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
*
*
* Authors:                  zhoujian
* Email:            343600434@qq.com
* Date:         Aug-28-2025 13:20:16
*
*/


#include "shuffle.h"
#include "play_card.h"
#include "key.h"
#include "menu.h"
#include "lcd.h"

#include "gui.h"
#include "user_motor_drv.h"
#include "log.h"
#include "input_check.h"
#include "flash.h"
#include "user_io.h"
#include "main.h"
#include "gui.h"


uint32_t adc_value[8];
uint8_t adc_index = 0;


void shuffle_adc_in()
{
    xi_left = ((uint32_t)(adc_buf[SHF_HW_ADC] * 120 / adc_buf[INTER_ADC]));
    //xi_right = ((uint32_t)(adc_buf[5] * 120 / adc_buf[10]));
    adc_value[adc_index++] =  xi_left;
    adc_index &= 7;
}



uint32_t shuffle_adc_first()
{
    xi_left = ((uint32_t)(adc_buf[SHF_HW_ADC] * 120 / adc_buf[INTER_ADC]));
    //xi_right = ((uint32_t)(adc_buf[5] * 120 / adc_buf[10]));
    adc_value[0] = xi_left;
    adc_value[1] = adc_value[0];
    adc_value[2] = adc_value[0];
    adc_value[3] = adc_value[0];
    adc_value[4] = adc_value[0];
    adc_value[5] = adc_value[0];
    adc_value[6] = adc_value[0];
    adc_value[7] = adc_value[0];
    adc_index = 1;
    log_info("\t adc=%d\n", adc_value[0]);
    return adc_value[0];
}

uint32_t last_adc()
{
    return adc_value[(adc_index - 1) & 7];
}


uint8_t last_three_changed()
{
    uint32_t now_v, pre1_v, pre2_v;
    uint8_t pokering = 0;
    now_v = adc_value[(adc_index - 1) & 7];
    pre1_v = adc_value[(adc_index - 1 - 1) & 7];
    pre2_v = adc_value[(adc_index - 1 - 2) & 7];
    //log_info("adc_index=%d <%d=%d %d=%d %d=%d>\n", adc_index, (adc_index - 1) & 7, now_v, (adc_index - 1 - 1) & 7, pre1_v, (adc_index - 1 - 2) & 7, pre2_v);

    if(pre1_v == 0) {
    } else if(pre2_v == 0) {
    } else {
        if(now_v > pre2_v) {
            if(now_v - pre2_v > 12) {
                if(pre1_v > pre2_v) {
                    if(pre1_v - pre2_v > 12) {
                        pokering = POKER_FALLINTO;
                    }
                }
            }

        } else {
            if(pre2_v - now_v > 12) {
                if(pre2_v > pre1_v) {
                    if(pre2_v - pre1_v > 12) {
                        pokering = POKER_FALLING;
                    }
                }
            }
        }

        if(pokering == POKER_FALLINTO) {
            log_info("pokering POKER_FALLINTO\n");

        } else if(pokering == POKER_FALLING) {
            log_info("pokering POKER_FALLING\n");
        }
    }

    return pokering;
}

uint8_t no_poker_need_shuffle;

uint8_t hopper_is_full()
{
    static uint16_t pre_adcv = 9999;
    //static uint16_t pre_adcv2 = 9999;
    uint16_t adcv;
    //static uint8_t check_times;

    /*if(update) {
       pre_adcv = 9999;
       pre_adcv2 = 9999;
    }*/

    if(pre_adcv != adc_buf[SHF_HW_ADC]) {
        xi_left = ((uint32_t)(adc_buf[SHF_HW_ADC] * 120 / adc_buf[INTER_ADC]));
        pre_adcv = adc_buf[SHF_HW_ADC];
        //GUI_ShowNum_2(40, 80, xi_left, 4, 16, 1);
    }

    if(xi_left <= 230) {
        // check_times++;
        // if(check_times > 2) {
        log_error("hopper is full %d\n", xi_left);
        return 1;
        // } else {
        //    log_error("hopper not full %d %d\n", xi_left, check_times);
        //     return 0;
        // }
    }

    log_error("hopper not full %d\n", xi_left);
    //check_times = 0;
    return 0;
}


uint8_t hopper_is_empty()
{
    static uint16_t pre_adcv = 9999;
    uint16_t adcv;

    /* if(update) {
       pre_adcv = 9999;
       pre_adcv2 = 9999;
     }*/

    if(pre_adcv != adc_buf[SHF_HW_ADC]) {
        xi_left = ((uint32_t)(adc_buf[SHF_HW_ADC] * 120 / adc_buf[INTER_ADC]));
        pre_adcv = adc_buf[SHF_HW_ADC];
        //GUI_ShowNum_2(40, 80, xi_left, 4, 16, 1);
    }

    if((xi_left >= 310)) {
        log_error("hopper is empty	 %d\n", xi_left);
        return 1;
    }

    log_error("hopper not empty	 %d\n", xi_left);
    return 0;
}
void check_no_shuffle(uint32_t adc)
{
    uint32_t now_adc;
    now_adc = last_adc();

    if(now_adc > adc) {
        if(now_adc > adc + 3) {
            no_poker_need_shuffle = 1;
            log_info("->no_poker_need_shuffle %d -> %d\n", adc, now_adc);
        }

    } else {
        if(adc > now_adc + 3) {
            no_poker_need_shuffle = 1;
            log_info("->no_poker_need_shuffle %d -> %d\n", adc, now_adc);
        }
    }
}
#define REV_SHUFFLE_TIME        3
#define REV_SHUFFLE_DELAY       5
#define SHUFFLE_ON_DELAY        16
#define SHUFFLE_OFF_DELAY       10
#define SHUFFLE_ONCE_TIME       5


//1:fsm 0:no fsm
#ifdef SHUFFLE_STATE_MACHINE


ShuffleStateMachine sm;

// 初始化状态机
void shuffle_state_machine_init(ShuffleStateMachine* sm, uint8_t force)
{
    sm->current_state = STATE_IDLE;
    sm->shuffle_once_state = SHUFFLE_ONCE_IDLE;
    sm->shuffle_rev_state = SHUFFLE_REV_IDLE;
    sm->force = force;
    sm->start_time = 0;
    sm->i = 0;
    sm->adj_delay = 20;
    sm->poker_entering = 0;
    sm->adc = 0;
    sm->pre_adc = 0;
    sm->continue_send_ = 0;
    sm->retry_count = 0;
    sm->delay_start_time = 0;
    sm->sel = 0;
    sm->rev_i = 0;
}

void shuffle_init()
{
    shuffle_state_machine_init(&sm, 1);
}

uint32_t get_current_time()
{
    return system_1ms_cnt;
}
// 检查是否延迟完成
uint8_t is_delay_complete(uint32_t start_time, uint32_t delay_ms)
{
    return (get_current_time() - start_time) >= delay_ms;
}

// 反向洗牌状态机
uint8_t shuffle_once_rev_step(ShuffleStateMachine* sm)
{
    switch(sm->shuffle_rev_state) {
        case SHUFFLE_REV_IDLE:
            log_info("-----------\n");
            sm->adc = shuffle_adc_first();
            sm->rev_i = 0;
            sm->shuffle_rev_state = SHUFFLE_REV_START;
            break;

        case SHUFFLE_REV_START:
            start_right_shuffle_rev();
            start_left_shuffle_rev();
            sm->delay_start_time = get_current_time();
            sm->shuffle_rev_state = SHUFFLE_REV_DELAY1;
            break;

        case SHUFFLE_REV_DELAY1:
            if(is_delay_complete(sm->delay_start_time, REV_SHUFFLE_DELAY)) {
                sm->shuffle_rev_state = SHUFFLE_REV_ADC1;
            }

            break;

        case SHUFFLE_REV_ADC1:
            shuffle_adc_in();
            sm->shuffle_rev_state = SHUFFLE_REV_STOP;
            break;

        case SHUFFLE_REV_STOP:
            stop_right_shuffle();
            stop_left_shuffle();
            sm->delay_start_time = get_current_time();
            sm->shuffle_rev_state = SHUFFLE_REV_DELAY2;
            break;

        case SHUFFLE_REV_DELAY2:
            if(is_delay_complete(sm->delay_start_time, REV_SHUFFLE_DELAY)) {
                sm->shuffle_rev_state = SHUFFLE_REV_ADC2;
            }

            break;

        case SHUFFLE_REV_ADC2:
            shuffle_adc_in();
            sm->shuffle_rev_state = SHUFFLE_REV_CHECK_ENTERING;
            break;

        case SHUFFLE_REV_CHECK_ENTERING:
            sm->poker_entering = last_three_changed();

            // 原代码条件: !poker_entering && i++ > REV_SHUFFLE_TIME
            // 注意：原代码是do-while，所以至少执行一次，然后检查条件
            if(!sm->poker_entering && (sm->rev_i++ > REV_SHUFFLE_TIME)) {
                // 条件成立，继续循环
                sm->shuffle_rev_state = SHUFFLE_REV_START;

            } else {
                sm->shuffle_rev_state = SHUFFLE_REV_COMPLETE;
            }

            break;

        case SHUFFLE_REV_COMPLETE:
            sm->shuffle_rev_state = SHUFFLE_REV_IDLE;
            return 1; // Complete

        default:
            sm->shuffle_rev_state = SHUFFLE_REV_IDLE;
            break;
    }

    return 0; // Not complete
}


// 单次洗牌状态机
uint8_t shuffle_once_step(ShuffleStateMachine* sm)
{
    switch(sm->shuffle_once_state) {
        case SHUFFLE_ONCE_IDLE:
            sm->shuffle_once_state = SHUFFLE_ONCE_FIRST_DIRECTION;
            break;

        case SHUFFLE_ONCE_FIRST_DIRECTION:
            start_right_shuffle();
            start_left_shuffle();
            sm->delay_start_time = get_current_time();
            sm->shuffle_once_state = SHUFFLE_ONCE_FIRST_DELAY;
            break;

        case SHUFFLE_ONCE_FIRST_DELAY:
            if(is_delay_complete(sm->delay_start_time, sm->adj_delay)) {
                sm->shuffle_once_state = SHUFFLE_ONCE_FIRST_ADC;
            }

            break;

        case SHUFFLE_ONCE_FIRST_ADC:
            shuffle_adc_in();
            stop_right_shuffle();
            stop_left_shuffle();
            sm->delay_start_time = get_current_time();
            sm->shuffle_once_state = SHUFFLE_ONCE_SECOND_DIRECTION;
            break;

        case SHUFFLE_ONCE_SECOND_DIRECTION:
            if(is_delay_complete(sm->delay_start_time, sm->adj_delay)) {
                sm->delay_start_time = get_current_time();
                sm->shuffle_once_state = SHUFFLE_ONCE_COMPLETE;
            }

            break;

        case SHUFFLE_ONCE_COMPLETE:
            sm->shuffle_once_state = SHUFFLE_ONCE_IDLE;
            return 1; // Complete

        default:
            sm->shuffle_once_state = SHUFFLE_ONCE_IDLE;
            break;
    }

    return 0; // Not complete
}

// 主状态机执行函数
void shuffle_state_machine_step(ShuffleStateMachine* sm)
{
    switch(sm->current_state) {
        case STATE_IDLE:
            //log_info("%s\n", __func__);
            break;

        case STATE_START:
            sm->adc = shuffle_adc_first();
            sm->current_state = STATE_CHECK_FORCE;
            break;

        case STATE_CHECK_FORCE:
            if(sm->force == 0) {
                sm->continue_send_++;

                if(sm->continue_send_ > 3) {
                    if(sm->adc > sm->pre_adc) {
                        if(sm->adc - sm->pre_adc < 5) {
                            sm->force = 1;
                            log_error("\t adc no change force\t");
                            sm->continue_send_ = 0;
                        }

                    } else {
                        if(sm->pre_adc - sm->adc < 5) {
                            sm->force = 1;
                            log_error("\t adc no change force\t");
                            sm->continue_send_ = 0;
                        }
                    }

                } else {
                    if(sm->continue_send_ > 1) {
                        if(sm->adc > 320) {
                            sm->force = 1;
                            log_error("\t adc no change force\t");
                            sm->continue_send_ = 0;
                        }
                    }
                }

            } else {
                sm->continue_send_ = 0;
            }

            sm->pre_adc = sm->adc;
            log_error("\t shuffle_card force %d %d\n", sm->force, sm->continue_send_);
            sm->poker_entering = 0;

            if(sm->force == 0) {
                if(no_poker_need_shuffle) {
                    log_info("no_poker_need_shuffle\n");
                    sm->current_state = STATE_STOP_SHUFFLE;
                    return;
                }
            }

            if(sm->force) {
                sm->current_state = STATE_FORCE_SHUFFLE_REV;

            } else {
                sm->current_state = STATE_CHECK_POKER_ENTERING;
            }

            break;

        case STATE_FORCE_SHUFFLE_REV:
            if(shuffle_once_rev_step(sm)) {
                sm->delay_start_time = get_current_time();
                sm->i = 0;
                sm->current_state = STATE_FORCE_SHUFFLE_LOOP;
            }

            break;

        case STATE_FORCE_SHUFFLE_LOOP:
            if(is_delay_complete(sm->delay_start_time, 1)) {
                if(sm->i < 5) {
                    if(shuffle_once_step(sm)) {
                        sm->i++;
                        sm->delay_start_time = get_current_time();
                    }

                } else {
                    sm->poker_entering = last_three_changed();

                    if(sm->poker_entering == 0) {
                        log_info("poker not entering\n");
                        check_no_shuffle(sm->adc);
                    }

                    sm->current_state = STATE_CHECK_POKER_ENTERING;
                }
            }

            break;

        case STATE_CHECK_POKER_ENTERING:
            if(hopper_is_empty() || sm->poker_entering) {
                //shuffle_once_step(sm); // Start first shuffle
                sm->start_time = 15; // 3s
                sm->current_state = STATE_CONTINUOUS_SHUFFLE;

            } else {
                sm->current_state = STATE_STOP_SHUFFLE;
            }

            break;

        case STATE_CONTINUOUS_SHUFFLE:
            if(shuffle_once_step(sm)) { // If shuffle complete
                sm->poker_entering = last_three_changed();

                if(sm->poker_entering == 0) {
                    check_no_shuffle(sm->adc);
                    sm->current_state = STATE_STOP_SHUFFLE;
                    break;
                }

                if(sm->start_time > 0 && !hopper_is_full()) {
                    sm->start_time--;
                    shuffle_once_step(sm); // Start next shuffle

                } else {
                    sm->current_state = STATE_STOP_SHUFFLE;
                }
            }

            break;

        case STATE_STOP_SHUFFLE:
            stop_shuffle();
            sm->current_state = STATE_IDLE; // Return to idle state
            break;

        case STATE_ERROR:
            // Error handling logic
            stop_shuffle();
            log_error("Shuffle state machine error\n");
            sm->current_state = STATE_IDLE;
            break;
    }
}

// 外部调用接口，替换原来的 shuffle_card_1 函数
void shuffle_card_1(uint8_t force)
{
    //static uint8_t initialized = 0;
    //if(!initialized) {
    //  initialized = 1;
    //} else {
    sm.force = force; // Update force parameter
    //}

    if(sm.current_state == STATE_IDLE) {
        sm.current_state = STATE_START;

        if(sm.force & 0x2) {
            if(sm.adj_delay < 100) {
                sm.adj_delay += 8;
            }

        } else {
            if(sm.adj_delay >= 20 + 4) {
                sm.adj_delay -= 4;
            }
        }

        log_info("\t\t adj_delay=%d\n", sm.adj_delay);
    }
}


#else


uint8_t shuffle_one_sheet(uint8_t right)
{
    uint32_t now_adc;
    uint8_t i = 0;//,add_sp;

    if(right) {
        log_info("\t\t>>>>>>>>>>>\n");

    } else {
        log_info("\t\t<<<<<<<<<\n");
    }

    uint8_t adc_compare[3];

    //uint32_t first_adc = shuffle_adc_first();
    //add_sp=1;

    do {
        if(right) {
            start_right_shuffle();

        } else {
            start_left_shuffle();
        }

        sys_ms_delay(30);//1->8
        //if(add_sp<4)add_sp++;
        shuffle_adc_in();
        now_adc = last_adc();

        //log_info("\t\t>>>>>>>>>>>\n");
        //log_info("\t\tfirst_adc=%d now_adc=%d  %d\n",first_adc,now_adc,now_adc-first_adc);
        if(right) {
            stop_right_shuffle();

        } else {
            stop_left_shuffle();
        }

        sys_ms_delay(20);
        uint8_t a = last_three_changed();

        if(a == POKER_FALLING) {
            break;

        } else if(a == POKER_FALLINTO) {
            return 0;
        }

        //shuffle_adc_in();
        //sys_delay(2);
        log_info("\t\t now_adc=%d\n", now_adc);
    } while(i++ < 14);

    if(i == 15) {
        return 1;
    }

    i = 0;

    do {
        if(right) {
            start_right_shuffle();

        } else {
            start_left_shuffle();
        }

        sys_ms_delay(25);
        shuffle_adc_in();
        now_adc = last_adc();

        //log_info("\t\t>>>>>>>>>>>\n");
        //log_info("\t\tfirst_adc=%d now_adc=%d  %d\n",first_adc,now_adc,now_adc-first_adc);
        if(right) {
            stop_right_shuffle();

        } else {
            stop_left_shuffle();
        }

        sys_ms_delay(25);
        uint8_t a = last_three_changed();

        if(a == POKER_FALLING) {
            ;

        } else if(a == POKER_FALLINTO) {
            return 0;
        }

        //shuffle_adc_in();
        //sys_delay(2);
        log_info("\t\t now_adc=%d\n", now_adc);
    } while(i++ < 5);

    if(i == 6) {
        return 1;
    }

#if 0
    start_left_shuffle();
    log_info("\t<<<<<<<<<<<<<<\n");
    sys_ms_delay(2);
    shuffle_adc_in();
    stop_left_shuffle();
    sys_ms_delay(3);
#endif
    return 0;
}
///////////////////////////////////////////


void shuffle_once_rev()
{
    log_info("-----------\n");
    uint8_t i, poker_entering;
    uint32_t adc = shuffle_adc_first();
    uint32_t now_adc;
    i = 0;

    do {
        start_right_shuffle_rev();
        start_left_shuffle_rev();
        sys_ms_delay(REV_SHUFFLE_DELAY);
        shuffle_adc_in();
        stop_right_shuffle();
        stop_left_shuffle();
        sys_ms_delay(REV_SHUFFLE_DELAY);
        shuffle_adc_in();
        poker_entering = last_three_changed();
    } while(!poker_entering && i++ < REV_SHUFFLE_TIME);
}


void shuffle_once()
{
    log_info("\t\t+++++++++++++++\n");
    start_right_shuffle();
    start_left_shuffle();
    sys_ms_delay(SHUFFLE_ON_DELAY);
    shuffle_adc_in();
    stop_right_shuffle();
    stop_left_shuffle();
    sys_ms_delay(SHUFFLE_OFF_DELAY);
}
void shuffle_once_bak()
{
    static uint8_t sel;

    if(sel) {
        log_info("\t\t>>>>>>>>>>>\n");
        start_right_shuffle();
        sys_ms_delay(16);
        shuffle_adc_in();
        stop_right_shuffle();

    } else {
        log_info("\t\t<<<<<<<<<<<\n");
        start_left_shuffle();
        sys_ms_delay(16);
        shuffle_adc_in();
        stop_left_shuffle();
    }

    sys_ms_delay(10);

    if(sel) {
        sel = 0;
        log_info("\t\t<<<<<<<<<<<\n");
        start_left_shuffle();
        sys_ms_delay(16);
        shuffle_adc_in();
        stop_left_shuffle();

    } else {
        log_info("\t\t>>>>>>>>>>>\n");
        start_right_shuffle();
        sys_ms_delay(16);
        shuffle_adc_in();
        stop_right_shuffle();
        sel = 1;
    }

    sys_ms_delay(10);
}


void shuffle_card_1(uint8_t force)
{
    uint8_t start_time;
    uint8_t i, poker_entering;
    static uint8_t continue_send_ = 0;
    static uint32_t pre_adc = 0;
    uint32_t adc = shuffle_adc_first();
    uint32_t now_adc;
    log_info("%s\n", __func__);
#ifdef NO_SHUFFLE_CARD
    return;
#endif

    if(force == 0) {
        continue_send_++;

        if(continue_send_ > 2) {
            if(adc > pre_adc) {
                if(adc - pre_adc < 5) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }

            } else {
                if(pre_adc - adc < 5) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }
            }

        } else {
            if(continue_send_ > 1) {
                if(adc > 320) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }
            }
        }

    } else {
        continue_send_ = 0;
    }

    pre_adc = adc;
    uint16_t adcv;
    log_error("\t shuffle_card force %d %d\n", force, continue_send_);
    poker_entering = 0;

    if(force == 0) {
        if(no_poker_need_shuffle) {
            log_info("no_poker_need_shuffle\n");
            return;
        }
    }

    if(force) {
        shuffle_once_rev();
        //shuffle_once();
        sys_delay(1);

        for(i = 0; i < SHUFFLE_ONCE_TIME; i++) {
            shuffle_once();
            //shuffle_adc_in();
            poker_entering = last_three_changed();
            //stop_shuffle();

            if(poker_entering == 0) {
                log_info("poker not entering\n");
                check_no_shuffle(adc);
            }
        }
    }

    if(hopper_is_empty() || poker_entering) {
        //shuffle
        //shuffle_once();
        start_time = 15; //3s

        do {
            //if((start_time%8)==){
            shuffle_once();
            poker_entering = last_three_changed();

            if(poker_entering == 0) {
                check_no_shuffle(adc);
                break;
            }

            sys_delay(1);
        } while((start_time--) && (!hopper_is_full()));

        //stop shuffle
    }

    stop_shuffle();
    //log_info("\n", adc_value[i]);
}


void shuffle_card_2(uint8_t force)
{
    static uint8_t sel = 0;
    uint8_t i, poker_entering;
    static uint8_t continue_send_ = 0;
    static uint32_t pre_adc = 0;
    uint32_t now_adc;
    uint32_t adc = shuffle_adc_first();

    if(force == 0) {
        //force = check_mandatory(adc,pre_adc,continue_send_);
        continue_send_++;

        if(continue_send_ > 3) {
            if(adc > pre_adc) {
                if(adc - pre_adc < 5) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }

            } else {
                if(pre_adc - adc < 5) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }
            }

        } else {
            if(continue_send_ > 1) {
                if(adc > 320) {
                    force = 1;
                    log_error("\t adc no change force\t");
                    continue_send_ = 0;
                }
            }
        }

    } else {
        continue_send_ = 0;
    }

    pre_adc = adc;

    if(force == 0) {
        if(no_poker_need_shuffle) {
            log_info("no_poker_need_shuffle\n");
            return;
        }
    }

    poker_entering = 1;

    if(force) {
        if(sel) {
            if(shuffle_one_sheet(1)) {
                if(shuffle_one_sheet(0)) {
                    check_no_shuffle(adc);
                    poker_entering = 0;
                }
            }

        } else {
            if(shuffle_one_sheet(0)) {
                if(shuffle_one_sheet(1)) {
                    check_no_shuffle(adc);
                    poker_entering = 0;
                }
            }
        }

        if(poker_entering == 0) {
            log_info("poker not entering\n");

        } else {
            sys_delay(10);
        }
    }

    if(hopper_is_empty() /*|| poker_entering*/) {
        if(sel) {
            if(shuffle_one_sheet(1)) {
                if(shuffle_one_sheet(0)) {
                    check_no_shuffle(adc);
                    poker_entering = 0;
                }
            }

        } else {
            if(shuffle_one_sheet(0)) {
                if(shuffle_one_sheet(1)) {
                    check_no_shuffle(adc);
                    poker_entering = 0;
                }
            }
        }
    }

    if(sel) {
        sel = 0;

    } else {
        sel = 1;
    }
}

#endif


